#!/usr/bin/env python
#-*- coding: utf-8 -*-

import gtk
import pango
import os

class CommonOption(object):
	def __init__(self, label, value):
		self.label = label
		self.value = value
		self.widget = None
		
class StringOption(CommonOption):
	def createWidget(self):
		if self.value == None:
			self.value = ""
		entry = gtk.Entry()
		entry.set_text(self.value)
		self.widget = entry
		return entry
	
	def getValue(self):
		return self.widget.get_text()

class IntegerOption(CommonOption):
	def __init__(self, label, value, lower = 0.0, upper = 100.0, step = 1.0):
		CommonOption.__init__(self, label, value)
		self.lower = lower
		self.upper = upper
		self.step = step
		
	def createWidget(self):
		if self.value == None:
			self.value = self.lower
		adjustment = gtk.Adjustment(self.value, self.lower, self.upper, self.step, self.step, self.step)
		spin = gtk.SpinButton(adjustment, self.step, digits=0)
		self.widget = spin
		return spin
		
	def getValue(self):
		return int(self.widget.get_value())
		
class BooleanOption(CommonOption):
	def createWidget(self):
		check = gtk.CheckButton(label="", use_underline=False)
		check.set_active(self.value)
		self.widget = check
		return check
	
	def getValue(self):
		return self.widget.get_active()
		
class FloatOption(CommonOption):
	def __init__(self, label, value, lower = 0.0, upper = 100.0, step = 1.0, digits = 2):
		CommonOption.__init__(self, label, value)
		self.lower = lower
		self.upper = upper
		self.step = step
		self.digits = digits
		
	def createWidget(self):
		adjustment = gtk.Adjustment(self.value, self.lower, self.upper, self.step, self.step, self.step)
		spin = gtk.SpinButton(adjustment , self.step, self.digits)
		self.widget = spin
		return spin
	
	def getValue(self):
		return float(self.widget.get_value())
		
class SelectionOption(CommonOption):
	def createWidget(self):
		combobox = gtk.combo_box_new_text()
		for item in self.value:
			combobox.append_text(item)
		combobox.set_active(0)
		self.widget = combobox
		return combobox
	
	def getValue(self):
		model = self.widget.get_model()
		active = self.widget.get_active()
		if active < 0:
			return None
		return model[active][0]


class FileOption(CommonOption):
	def __init__(self, label, value):
		CommonOption.__init__(self, label, value)
		
	def createWidget(self):
		fileChooserButton = gtk.FileChooserButton("Choose a file")
		if os.path.exists(self.value):
			fileChooserButton.select_filename(self.value)
		self.widget = fileChooserButton
		return fileChooserButton
		
	def getValue(self):
		return self.widget.get_filename()
		
class OptionDialog(object):
	def __init__(self, title = "", parent = None):
		flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
		buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
		self.dialog = gtk.Dialog(title, parent, flags, buttons)

	def run(self, options):
		maxNameLength = 0
		for option in options:
			maxNameLength = max(maxNameLength, len(option.label))
			
		for option in options:
			hBox = gtk.HBox()
			label = gtk.Label()
			label.set_text(option.label)
			label.set_width_chars(maxNameLength + 2)
			label.set_alignment(0.0, 0.5)
			hBox.pack_start(label, False, False, 0)
			hBox.pack_start(option.createWidget())
			self.dialog.vbox.pack_start(hBox, True, True, 0)
			self.dialog.show_all()
			
		response = self.dialog.run()
		self.dialog.destroy()
		
		if response == gtk.RESPONSE_ACCEPT:
			newValues = []
			for option in options:
				newValues.append(option.getValue())
			return newValues
		else:
			return None

if __name__ == "__main__":
	optionDialog = OptionDialog("Title", None)
	options = [
		StringOption("StringOption", "value"),
		IntegerOption("IntegerOption", 1),
		BooleanOption("BooleanOption", True),
		FloatOption("FloatOption", 1.00),
		SelectionOption("SelectionOption", ["One", "Two", "Three"]),
		FileOption("FileOption", "/home")
	]
	print optionDialog.run(options)
	gtk.main()
